home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-02 | 55.5 KB | 1,304 lines |
- Newsgroups: comp.sources.misc
- From: daveg@synaptics.com (David Gillespie)
- Subject: v24i100: gnucalc - GNU Emacs Calculator, v2.00, Part52/56
- Message-ID: <1991Nov3.001107.19867@sparky.imd.sterling.com>
- X-Md4-Signature: 00b5266219e8700dca42990e322ca57d
- Date: Sun, 3 Nov 1991 00:11:07 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: daveg@synaptics.com (David Gillespie)
- Posting-number: Volume 24, Issue 100
- Archive-name: gnucalc/part52
- Environment: Emacs
- Supersedes: gmcalc: Volume 13, Issue 27-45
-
- #!/bin/sh
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file calc.texinfo continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 52; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping calc.texinfo'
- else
- echo 'x - continuing file calc.texinfo'
- sed 's/^X//' << 'SHAR_EOF' >> 'calc.texinfo' &&
- X
- @kindex Z E
- @pindex calc-user-define-edit
- @cindex Editing user definitions
- The @kbd{Z E} (@code{calc-user-define-edit}) command edits the definition
- of a user key. This works for keys that have been defined by either
- keyboard macros or formulas; further details are contained in the relevant
- following sections.
- X
- @node Keyboard Macros, Invocation Macros, Creating User Keys, Programming
- @section Programming with Keyboard Macros
- X
- @noindent
- @kindex X
- @cindex Programming with keyboard macros
- @cindex Keyboard macros
- The easiest way to ``program'' the Emacs Calculator is to use standard
- keyboard macros. Press @kbd{C-x (} to begin recording a macro. From
- this point on, keystrokes you type will be saved away as well as
- performing their usual functions. Press @kbd{C-x )} to end recording.
- Press shift-@kbd{X} (or the standard Emacs key sequence @kbd{C-x e}) to
- execute your keyboard macro by replaying the recorded keystrokes.
- @xref{Keyboard Macros, , , emacs, the Emacs Manual}, for further
- information.@refill
- X
- When you use @kbd{X} to invoke a keyboard macro, the entire macro is
- treated as a single command by the undo and trail features. The stack
- display buffer is not updated during macro execution, but is instead
- fixed up once the macro completes. Thus, commands defined with keyboard
- macros are convenient and efficient. The @kbd{C-x e} command, on the
- other hand, invokes the keyboard macro with no special treatment: Each
- command in the macro will record its own undo information and trail entry,
- and update the stack buffer accordingly. If your macro uses features
- outside of Calc's control to operate on the contents of the Calc stack
- buffer, or if it includes Undo, Redo, or last-arguments commands, you
- must use @kbd{C-x e} to make sure the buffer and undo list are up-to-date
- at all times. You could also consider using @kbd{K} (@code{calc-keep-args})
- instead of @kbd{M-@key{RET}} (@code{calc-last-args}).
- X
- Calc extends the standard Emacs keyboard macros in several ways.
- Keyboard macros can be used to create user-defined commands. Keyboard
- macros can include conditional and iteration structures, somewhat
- analogous to those provided by a traditional programmable calculator.
- X
- @menu
- * Naming Keyboard Macros::
- * Conditionals in Macros::
- * Loops in Macros::
- * Local Values in Macros::
- * Queries in Macros::
- @end menu
- X
- @node Naming Keyboard Macros, Conditionals in Macros, Keyboard Macros, Keyboard Macros
- @subsection Naming Keyboard Macros
- X
- @noindent
- @kindex Z K
- @pindex calc-user-define-kbd-macro
- Once you have defined a keyboard macro, you can bind it to a @kbd{z}
- key sequence with the @kbd{Z K} (@code{calc-user-define-kbd-macro}) command.
- This command prompts first for a key, then for a command name. For
- example, if you type @kbd{C-x ( n @key{TAB} n @key{TAB} C-x )} you will
- define a keyboard macro which negates the top two numbers on the stack
- (@key{TAB} swaps the top two stack elements). Now you can type
- @kbd{Z K n @key{RET}} to define this keyboard macro onto the @kbd{z n} key
- sequence. The default command name (if you answer the second prompt with
- just the @key{RET} key as in this example) will be something like
- @samp{calc-User-n}. The keyboard macro will now be available as both
- @kbd{z n} and @kbd{M-x calc-User-n}. You can backspace and enter a more
- descriptive command name if you wish.@refill
- X
- Macros defined by @kbd{Z K} act like single commands; they are executed
- in the same way as by the @kbd{X} key. If you wish to define the macro
- as a standard no-frills Emacs macro (to be executed as if by @kbd{C-x e}),
- give a negative prefix argument to @kbd{Z K}.
- X
- Once you have bound your keyboard macro to a key, you can use
- @kbd{Z P} to register it permanently with Emacs. @xref{Creating User Keys}.
- X
- @cindex Keyboard macros, editing
- The @kbd{Z E} (@code{calc-user-define-edit}) command on a key that has
- been defined by a keyboard macro tries to use the @code{edit-kbd-macro}
- command to edit the macro. This command may be found in the
- @file{macedit} package, a copy of which comes with Calc. It decomposes
- the macro definition into full Emacs command names, like @code{calc-pop}
- and @code{calc-add}. Type @kbd{M-# M-#} to finish editing and update
- the definition stored on the key, or, to cancel the edit, type
- @kbd{M-# x}.@refill
- X
- If you give a negative numeric prefix argument to @kbd{Z E}, the keyboard
- macro is edited in spelled-out keystroke form. For example, the editing
- buffer might contain the nine characters @samp{1 RET 2 +}. When you press
- @kbd{M-# M-#}, the @code{read-kbd-macro} feature of the @file{macedit}
- package is used to reinterpret these key names. The
- notations @code{RET}, @code{LFD}, @code{TAB}, @code{SPC}, @code{DEL}, and
- @code{NUL} must be written in all uppercase, as must the prefixes @code{C-}
- and @code{M-}. Spaces and line breaks are ignored. Other characters are
- copied verbatim into the keyboard macro. Basically, the notation is the
- same as is used in all of this manual's examples, except that the manual
- takes some liberties with spaces: When we say @kbd{' [1 2 3] RET}, we take
- it for granted that it is clear we really mean @kbd{' [1 SPC 2 SPC 3] RET},
- which is what @code{read-kbd-macro} wants to see.@refill
- X
- If @file{macedit} is not available, @kbd{Z E} edits the keyboard macro
- in ``raw'' form; the editing buffer simply contains characters like
- @samp{1^M2+} (here @samp{^M} represents the carriage-return character).
- Editing in this mode, you will have to use @kbd{C-q} to enter more
- control characters into the buffer.@refill
- X
- @node Conditionals in Macros, Loops in Macros, Naming Keyboard Macros, Keyboard Macros
- @subsection Conditionals in Keyboard Macros
- X
- @noindent
- @kindex Z [
- @kindex Z :
- @kindex Z |
- @kindex Z ]
- @pindex calc-kbd-if
- @pindex calc-kbd-else
- @pindex calc-kbd-else-if
- @pindex calc-kbd-end-if
- @cindex Conditional structures
- The @kbd{Z [} (@code{calc-kbd-if}) and @kbd{Z ]} (@code{calc-kbd-end-if})
- commands allow you to put simple tests in a keyboard macro. When Calc
- sees the @kbd{Z [}, it pops an object from the stack and, if the object is
- a non-zero value, continues executing keystrokes. But if the object is
- zero, or if it is not provably nonzero, Calc skips ahead to the matching
- @kbd{Z ]} keystroke. @xref{Logical Operations}, for a set of commands for
- performing tests which conveniently produce 1 for true and 0 for false.
- X
- For example, @kbd{@key{RET} 0 a < Z [ n Z ]} implements an absolute-value
- function in the form of a keyboard macro. To program this macro, type
- @kbd{C-x (},
- type the above sequence of keystrokes, then type @kbd{C-x )}. Note that
- the keystrokes will be executed while you are making the definition as
- well as when you later re-execute the macro by typing @kbd{X}. Thus you
- should make sure a suitable number is on the stack before defining the
- macro so that you don't get a stack-underflow error during the
- definition process.@refill
- X
- The above macro duplicates the number on the top of the stack, pushes
- zero and compares using @kbd{a <} (@code{calc-less-than}), then, if
- the number was less than zero, executes @kbd{n} (@code{calc-change-sign}).
- Otherwise, the change-sign command is skipped.
- X
- Conditionals can be nested arbitrarily. However, there should be exactly
- one @kbd{Z ]} for each @kbd{Z [} in a keyboard macro.
- X
- The @kbd{Z :} (@code{calc-kbd-else}) command allows you to choose between
- two keystroke sequences. The general format is @kbd{@var{cond} Z [
- @var{then-part} Z : @var{else-part} Z ]}. If @var{cond} is true
- (i.e., if the top of stack contains a non-zero number after @var{cond}
- has been executed), the @var{then-part} will be executed and the
- @var{else-part} will be skipped. Otherwise, the @var{then-part} will
- be skipped and the @var{else-part} will be executed.
- X
- The @kbd{Z |} (@code{calc-kbd-else-if}) command allows you to choose
- between any number of alternatives. For example,
- @kbd{@var{cond1} Z [ @var{part1} Z : @var{cond2} Z | @var{part2} Z :
- @var{part3} Z ]} will execute @var{part1} if @var{cond1} is true,
- otherwise it will execute @var{part2} if @var{cond2} is true, otherwise
- it will execute @var{part3}.
- X
- More precisely, @kbd{Z [} pops a number and conditionally skips to the
- next matching @kbd{Z :} or @kbd{Z ]} key. @kbd{Z ]} has no effect when
- actually executed. @kbd{Z :} skips to the next matching @kbd{Z ]}.
- @kbd{Z |} pops a number and conditionally skips to the next matching
- @kbd{Z :} or @kbd{Z ]}; thus, @kbd{Z [} and @kbd{Z |} are functionally
- equivalent except that @kbd{Z [} participates in nesting but @kbd{Z |}
- does not.
- X
- Calc's conditional and looping constructs work by scanning the
- keyboard macro for occurrences of character sequences like @samp{Z:}
- and @samp{Z]}. One side-effect of this is that if you use these
- constructs you must be careful that these character pairs do not
- occur by accident in other parts of the macros. Since Calc rarely
- uses shift-Z for any purpose except as a prefix character, this is
- not likely to be a problem. Another side-effect is that it will
- not work to define your own custom key bindings for these commands.
- Only the standard shift-Z bindings will work correctly.
- X
- The conditional and looping constructs are not actually tied to
- keyboard macros, but they are most often used in that context.
- For example, the keystrokes @kbd{10 Z < 23 @key{RET} Z >} push
- ten copies of 23 onto the stack. This can be typed ``live'' just
- as easily as in a macro definition.
- X
- @kindex Z C-g
- If Calc gets stuck while skipping characters during the definition of a
- macro, type @kbd{Z C-g} to cancel the definition. (Typing plain @kbd{C-g}
- actually adds a @kbd{C-g} keystroke to the macro.)
- X
- @node Loops in Macros, Local Values in Macros, Conditionals in Macros, Keyboard Macros
- @subsection Loops in Keyboard Macros
- X
- @noindent
- @kindex Z <
- @kindex Z >
- @pindex calc-kbd-repeat
- @pindex calc-kbd-end-repeat
- @cindex Looping structures
- @cindex Iterative structures
- The @kbd{Z <} (@code{calc-kbd-repeat}) and @kbd{Z >}
- (@code{calc-kbd-end-repeat}) commands pop a number from the stack,
- which must be an integer, then repeat the keystrokes between the brackets
- the specified number of times. If the integer is zero or negative, the
- body is skipped altogether. For example, @kbd{1 @key{TAB} Z < 2 * Z >}
- computes two to a nonnegative integer power. First, we push 1 on the
- stack and then swap the integer argument back to the top. The @kbd{Z <}
- pops that argument leaving the 1 back on top of the stack. Then, we
- repeat a multiply-by-two step however many times.@refill
- X
- Once again, the keyboard macro is executed as it is being entered.
- In this case it is especially important to set up reasonable initial
- conditions before making the definition: Suppose the integer 1000 just
- happened to be sitting on the stack before we typed the above definition!
- Another approach is to enter a harmless dummy definition for the macro,
- then go back and edit in the real one with a @kbd{Z E} command. Yet
- another approach is to type the macro as written-out keystroke names
- in a buffer, then use @kbd{M-# m} (@code{read-kbd-macro}) to read the
- macro.
- X
- @kindex Z /
- @pindex calc-break
- The @kbd{Z /} (@code{calc-kbd-break}) command allows you to break out
- of a keyboard macro loop prematurely. It pops an object from the stack;
- if that object is true (a non-zero number), control jumps out of the
- innermost enclosing @kbd{Z <} @dots{} @kbd{Z >} loop and continues
- after the @kbd{Z >}. If the object is false, the @kbd{Z /} has no
- effect. Thus @kbd{@var{cond} Z /} is similar to @samp{if (@var{cond}) break;}
- in the C language.@refill
- X
- @kindex Z (
- @kindex Z )
- @pindex calc-kbd-for
- @pindex calc-kbd-end-for
- The @kbd{Z (} (@code{calc-kbd-for}) and @kbd{Z )} (@code{calc-kbd-end-for})
- commands are similar to @kbd{Z <} and @kbd{Z >}, except that they make the
- value of the counter available inside the loop. The general layout is
- @kbd{@var{init} @var{final} Z ( @var{body} @var{step} Z )}. The @kbd{Z (}
- command pops initial and final values from the stack. It then creates
- a temporary internal counter and initializes it with the value @var{init}.
- The @kbd{Z (} command then repeatedly pushes the counter value onto the
- stack and executes @var{body} and @var{step}, adding @var{step} to the
- counter each time until the loop finishes.@refill
- X
- @cindex Summations (by keyboard macros)
- By default, the loop finishes when the counter becomes greater than (or
- less than) @var{final}, assuming @var{initial} is less than (greater
- than) @var{final}. If @var{initial} is equal to @var{final}, the body
- executes exactly once. The body of the loop always executes at least
- once. For example, @kbd{0 1 10 Z ( 2 ^ + 1 Z )} computes the sum of the
- squares of the integers from 1 to 10, in steps of 1.
- X
- If you give a numeric prefix argument of 1 to @kbd{Z (}, the loop is
- forced to use upward-counting conventions. In this case, if @var{initial}
- is greater than @var{final} the body will not be executed at all.
- Note that @var{step} may still be negative in this loop; the prefix
- argument merely constrains the loop-finished test. Likewise, a prefix
- argument of @i{-1} forces downward-counting conventions.
- X
- @kindex Z @{
- @kindex Z @}
- @pindex calc-kbd-loop
- @pindex calc-kbd-end-loop
- The @kbd{Z @{} (@code{calc-kbd-loop}) and @kbd{Z @}}
- (@code{calc-kbd-end-loop}) commands are similar to @kbd{Z <} and
- @kbd{Z >}, except that they do not pop a count from the stack---they
- effectively create an infinite loop. Every @kbd{Z @{} @dots{} @kbd{Z @}}
- loop ought to include at least one @kbd{Z /} to make sure the loop
- doesn't run forever. (If any error message occurs which causes Emacs
- to beep, the keyboard macro will also be halted; this is a standard
- feature of Emacs. You can also generally press @kbd{C-g} to halt a
- running keyboard macro, although not all versions of Unix support
- this feature.)
- X
- @xref{Conditionals in Macros}, for some additional notes about
- conditional and looping commands.
- X
- @node Local Values in Macros, Queries in Macros, Loops in Macros, Keyboard Macros
- @subsection Local Values in Macros
- X
- @noindent
- @cindex Local variables
- @cindex Restoring saved modes
- Keyboard macros sometimes want to operate under known conditions
- without affecting surrounding conditions. For example, a keyboard
- macro may wish to turn on Fraction Mode, or set a particular
- precision, independent of the user's normal setting for those
- modes.
- X
- @kindex Z `
- @kindex Z '
- @pindex calc-kbd-push
- @pindex calc-kbd-pop
- Macros also sometimes need to use local variables. Assignments to
- local variables inside the macro should not affect any variables
- outside the macro. The @kbd{Z `} (@code{calc-kbd-push}) and @kbd{Z '}
- (@code{calc-kbd-pop}) commands give you both of these capabilities.
- X
- When you type @kbd{Z `} (with a backquote or accent grave character),
- the values of various mode settings are saved away. The ten ``quick''
- variables @code{q0} through @code{q9} are also saved. When
- you type @kbd{Z '} (with an apostrophe), these values are restored.
- Pairs of @kbd{Z `} and @kbd{Z '} commands may be nested.
- X
- If a keyboard macro halts due to an error in between a @kbd{Z `} and
- a @kbd{Z '}, the saved values will be restored correctly even though
- the macro never reaches the @kbd{Z '} command. Thus you can use
- @kbd{Z `} and @kbd{Z '} without having to worry about what happens
- in exceptional conditions.
- X
- If you type @kbd{Z `} ``live'' (not in a keyboard macro), Calc puts
- you into a ``recursive edit.'' You can tell you are in a recursive
- edit because there will be extra square brackets in the mode line,
- as in @samp{[(Calculator)]}. These brackets will go away when you
- type the matching @kbd{Z '} command. The modes and quick variables
- will be saved and restored in just the same way as if actual keyboard
- macros were involved.
- X
- The modes saved by @kbd{Z `} and @kbd{Z '} are the current precision
- and word size, the angular mode (Deg, Rad, or HMS), the simplification
- mode, the matrix mapping direction, Algebraic mode, Symbolic mode,
- Infinite mode, Matrix or Scalar mode, Fraction mode, and the current
- complex mode (Polar or Rectangular). The ten ``quick'' variables'
- values (or lack thereof) are also saved.
- X
- Most mode-setting commands act as toggles, but with a numeric prefix
- they force the mode either on (positive prefix) or off (negative
- or zero prefix). Since you don't know what the environment might
- be when you invoke your macro, it's best to use prefix arguments
- for all mode-setting commands inside the macro.
- X
- In fact, @kbd{C-u Z `} is like @kbd{Z `} except that it sets the modes
- listed above to their default values. As usual, the matching @kbd{Z '}
- will restore the modes to their settings from before the @kbd{C-u Z `}.
- Also, @kbd{Z `} with a negative prefix argument resets the mapping
- direction and algebraic mode to their defaults but leaves the other
- modes the same as their values outside the construct.
- X
- The contents of the stack and trail, values of non-quick variables, and
- other settings such as the language mode and the various display modes,
- are @emph{not} affected by @kbd{Z `} and @kbd{Z '}.
- X
- @node Queries in Macros, , Local Values in Macros, Keyboard Macros
- @subsection Queries in Keyboard Macros
- X
- @noindent
- @kindex Z =
- @pindex calc-kbd-report
- The @kbd{Z =} (@code{calc-kbd-report}) command displays an informative
- message including the value on the top of the stack. You are prompted
- to enter a string. That string, along with the top-of-stack value,
- is displayed unless @kbd{m w} (@code{calc-working}) has been used
- to turn such messages off.
- X
- @kindex Z #
- @pindex calc-kbd-query
- The @kbd{Z #} (@code{calc-kbd-query}) command displays a prompt message
- (which you enter during macro definition), then does an algebraic entry
- which takes its input from the keyboard, even during macro execution.
- This command allows your keyboard macros to accept numbers or formulas
- as interactive input. All the normal conventions of algebraic input,
- including the use of @kbd{$} characters, are supported.
- @xref{Kbd Macro Query, , , emacs, the Emacs Manual}, for a description of
- @kbd{C-x q} (@code{kbd-macro-query}), the standard Emacs way to accept
- keyboard input during a keyboard macro. In particular, you can use
- @kbd{C-x q} to enter a recursive edit, which allows the user to perform
- any Calculator operations interactively before pressing @kbd{C-M-c} to
- return control to the keyboard macro.
- X
- @node Invocation Macros, Algebraic Definitions, Keyboard Macros, Programming
- @section Invocation Macros
- X
- @kindex M-# z
- @kindex Z I
- @pindex calc-user-invocation
- @pindex calc-user-define-invocation
- Calc provides one special keyboard macro, called up by @kbd{M-# z}
- (@code{calc-user-invocation}), that is intended to allow you to define
- your own special way of starting Calc. To define this ``invocation
- macro,'' create the macro in the usual way with @kbd{C-x (} and
- @kbd{C-x )}, then type @kbd{Z I} (@code{calc-user-define-invocation}).
- There is only one invocation macro, so you don't need to type any
- additional letters after @kbd{Z I}. From now on, you can type
- @kbd{M-# z} at any time to execute your invocation macro.
- X
- For example, suppose you find yourself often grabbing rectangles of
- numbers into Calc and multiplying their columns. You can do this
- by typing @kbd{M-# r} to grab, and @kbd{V R : *} to multiply columns.
- To make this into an invocation macro, just type @kbd{C-x ( M-# r
- V R : * C-x )}, then @kbd{Z I}. Then, to multiply a rectangle of data,
- just mark the data in its buffer in the usual way and type @kbd{M-# z}.
- X
- Invocation macros are treated like regular Emacs keyboard macros;
- all the special features described above for @kbd{Z K}-style macros
- to not apply. @kbd{M-# z} is just like @kbd{C-x e}, except that it
- uses the macro that was last stored by @kbd{Z I}. (In fact, the
- macro does not even have to have anything to do with Calc!)
- X
- The @kbd{m m} command saves the last invocation macro defined by
- @kbd{Z I} along with all the other Calc mode settings.
- @xref{General Mode Commands}.
- X
- @node Algebraic Definitions, Lisp Definitions, Invocation Macros, Programming
- @section Programming with Formulas
- X
- @noindent
- @kindex Z F
- @pindex calc-user-define-formula
- @cindex Programming with algebraic formulas
- Another way to create a new Calculator command uses algebraic formulas.
- The @kbd{Z F} (@code{calc-user-define-formula}) command stores the
- formula at the top of the stack as the definition for a key. This
- command prompts for five things: The key, the command name, the function
- name, the argument list, and the behavior of the command when given
- non-numeric arguments.
- X
- For example, suppose we type @kbd{' a+2b @key{RET}} to push the formula
- @samp{a + 2*b} onto the stack. We now type @kbd{Z F m} to define this
- formula on the @kbd{z m} key sequence. The next prompt is for a command
- name, beginning with @samp{calc-}, which should be the long (@kbd{M-x}) form
- for the new command. If you simply press @key{RET}, a default name like
- @code{calc-User-m} will be constructed. In our example, suppose we enter
- @kbd{spam @key{RET}} to define the new command as @code{calc-spam}.
- X
- If you want to give the formula a long-style name only, you can press
- @key{SPC} or @key{RET} when asked which single key to use. For example
- @kbd{Z F @key{RET} spam @key{RET}} defines the new command as
- @kbd{M-x calc-spam}, with no keyboard equivalent.
- X
- The third prompt is for a function name. The default is to use the same
- name as the command name but with @samp{calcFunc-} in place of
- @samp{calc-}. This is the name you will use if you want to enter your
- new function in an algebraic formula. Suppose we enter @kbd{yow @key{RET}}.
- Then the new function can be invoked by pushing two numbers on the
- stack and typing @kbd{z m} or @kbd{x spam}, or by entering the algebraic
- formula @samp{yow(x,y)}.@refill
- X
- The fourth prompt is for the function's argument list. This is used to
- associate values on the stack with the variables that appear in the formula.
- The default is a list of all variables which appear in the formula, sorted
- into alphabetical order. In our case, the default would be @samp{(a b)}.
- This means that, when the user types @kbd{z m}, the Calculator will remove
- two numbers from the stack, substitute these numbers for @samp{a} and
- @samp{b} (respectively) in the formula, then simplify the formula and
- push the result on the stack. In other words, @kbd{10 @key{RET} 100 z m}
- would replace the 10 and 100 on the stack with the number 210, which is
- @cite{a + 2 b} with @cite{a=10} and @cite{b=100}. Likewise, the formula
- @samp{yow(10, 100)} will be evaluated by substituting @cite{a=10} and
- @cite{b=100} in the definition.
- X
- You can rearrange the order of the names before pressing @key{RET} to
- control which stack positions go to which variables in the formula. If
- you remove a variable from the argument list, that variable will be left
- in symbolic form by the command. Thus using an argument list of @samp{(b)}
- for our function would cause @kbd{10 z m} to replace the 10 on the stack
- with the formula @samp{a + 20}. If we had used an argument list of
- @samp{(b a)}, the result with inputs 10 and 100 would have been 120.
- X
- You can also put a nameless function on the stack instead of just a
- formula, as in @samp{<a, b : a + 2 b>}. @xref{Specifying Operators}.
- In this example, the command will be defined by the formula @samp{a + 2 b}
- using the argument list @samp{(a b)}.
- X
- The final prompt is a y-or-n question concerning what to do if symbolic
- arguments are given to your function. If you answer @kbd{y}, then
- executing @kbd{z m} (using the original argument list @samp{(a b)}) with
- arguments @cite{10} and @cite{x} will leave the function in symbolic
- form, i.e., @samp{yow(10,x)}. On the other hand, if you answer @kbd{n},
- then the formula will always be expanded, even for non-constant
- arguments: @samp{10 + 2 x}. If you never plan to feed algebraic
- formulas to your new function, it doesn't matter how you answer this
- question.@refill
- X
- If you answered @kbd{y} to this question you can still cause a function
- call to be expanded by typing @kbd{a "} (@code{calc-expand-formula}).
- Also, Calc will expand the function if necessary when you take a
- derivative or integral or solve an equation involving the function.
- X
- @kindex Z G
- @pindex calc-get-user-defn
- Once you have defined a formula on a key, you can retrieve this formula
- with the @kbd{Z G} (@code{calc-user-define-get-defn}) command. Press a
- key, and this command pushes the formula that was used to define that
- key onto the stack. Actually, it pushes a nameless function that
- specifies both the argument list and the defining formula. You will get
- an error message if the key is undefined, or if the key was not defined
- by a @kbd{Z F} command.@refill
- X
- The @kbd{Z E} (@code{calc-user-define-edit}) command on a key that has
- been defined by a formula uses a variant of the @code{calc-edit} command
- to edit the defining formula. Press @kbd{M-# M-#} to finish editing and
- store the new formula back in the definition, or @kbd{M-# x} to
- cancel the edit. (The argument list and other properties of the
- definition are unchanged; to adjust the argument list, you can use
- @kbd{Z G} to grab the function onto the stack, edit with @kbd{`}, and
- then re-execute the @kbd{Z F} command.)
- X
- As usual, the @kbd{Z P} command records your definition permanently.
- In this case it will permanently record all three of the relevant
- definitions: the key, the command, and the function.
- X
- You may find it useful to turn off the default simplifications with
- @kbd{m O} (@code{calc-no-simplify-mode}) when entering a formula to be
- used as a function definition. For example, the formula @samp{deriv(a^2,v)}
- which might be used to define a new function @samp{dsqr(a,v)} will be
- ``simplified'' to 0 immediately upon entry since @code{deriv} considers
- @cite{a} to be constant with respect to @cite{v}. Turning off
- default simplifications cures this problem: the definition will be stored
- in symbolic form without ever activating the @code{deriv} function. Press
- @kbd{m D} to turn the default simplifications back on afterwards.
- X
- @node Lisp Definitions, , Algebraic Definitions, Programming
- @section Programming with Lisp
- X
- @noindent
- The Calculator can be programmed quite extensively in Lisp. All you
- do is write a normal Lisp function definition, but with @code{defmath}
- in place of @code{defun}. This has the same form as @code{defun}, but it
- automagically replaces calls to standard Lisp functions like @code{+} and
- @code{zerop} with calls to the corresponding functions in Calc's own library.
- Thus you can write natural-looking Lisp code which operates on all of the
- standard Calculator data types. You can then use @kbd{Z D} if you wish to
- bind your new command to a @kbd{z}-prefix key sequence. The @kbd{Z E} command
- will not edit a Lisp-based definition.
- X
- Emacs Lisp is described in the GNU Emacs Lisp Reference Manual. This section
- assumes a familiarity with Lisp programming concepts; if you do not know
- Lisp, you may find keyboard macros or rewrite rules to be an easier way
- to program the Calculator.
- X
- This section first discusses ways to write commands, functions, or
- small programs to be executed inside of Calc. Then it discusses how
- your own separate programs are able to call Calc from the outside.
- Finally, there is a list of internal Calc functions and data structures
- for the true Lisp enthusiast.
- X
- @menu
- * Defining Functions::
- * Defining Simple Commands::
- * Defining Stack Commands::
- * Argument Qualifiers::
- * Example Definitions::
- X
- * Calling Calc from Your Programs::
- * Internals::
- @end menu
- X
- @node Defining Functions, Defining Simple Commands, Lisp Definitions, Lisp Definitions
- @subsection Defining New Functions
- X
- @noindent
- @findex defmath
- The @code{defmath} function (actually a Lisp macro) is like @code{defun}
- except that code in the body of the definition can make use of the full
- range of Calculator data types. The prefix @samp{calcFunc-} is added
- to the specified name to get the actual Lisp function name. As a simple
- example,
- X
- @example
- (defmath myfact (n)
- X (if (> n 0)
- X (* n (myfact (1- n)))
- X 1))
- @end example
- X
- @noindent
- This actually expands to the code,
- X
- @example
- (defun calcFunc-myfact (n)
- X (if (math-posp n)
- X (math-mul n (calcFunc-myfact (math-add n -1)))
- X 1))
- @end example
- X
- @noindent
- This function can be used in algebraic expressions, e.g., @samp{myfact(5)}.
- X
- The @samp{myfact} function as it is defined above has the bug that an
- expression @samp{myfact(a+b)} will be simplified to 1 because the
- formula @samp{a+b} is not considered to be @code{posp}. A robust
- factorial function would be written along the following lines:
- X
- @smallexample
- (defmath myfact (n)
- X (if (> n 0)
- X (* n (myfact (1- n)))
- X (if (= n 0)
- X 1
- X nil))) ; this could be simplified as: (and (= n 0) 1)
- @end smallexample
- X
- If a function returns @code{nil}, it is left unsimplified by the Calculator
- (except that its arguments will be simplified). Thus, @samp{myfact(a+1+2)}
- will be simplified to @samp{myfact(a+3)} but no further. Beware that every
- time the Calculator reexamines this formula it will attempt to resimplify
- it, so your function ought to detect the returning-@code{nil} case as
- efficiently as possible.
- X
- The following standard Lisp functions are treated by @code{defmath}:
- @code{+}, @code{-}, @code{*}, @code{/}, @code{%}, @code{^} or
- @code{expt}, @code{=}, @code{<}, @code{>}, @code{<=}, @code{>=},
- @code{/=}, @code{1+}, @code{1-}, @code{logand}, @code{logior}, @code{logxor},
- @code{logandc2}, @code{lognot}. Also, @code{~=} is an abbreviation for
- @code{math-nearly-equal}, which is useful in implementing Taylor series.@refill
- X
- For other functions @var{func}, if a function by the name
- @samp{calcFunc-@var{func}} exists it is used, otherwise if a function by the
- name @samp{math-@var{func}} exists it is used, otherwise if @var{func} itself
- is defined as a function it is used, otherwise @samp{calcFunc-@var{func}} is
- used on the assumption that this is a to-be-defined math function. Also, if
- the function name is quoted as in @samp{('integerp a)} the function name is
- always used exactly as written (but not quoted).@refill
- X
- Variable names have @samp{var-} prepended to them unless they appear in
- the function's argument list or in an enclosing @code{let}, @code{let*},
- @code{for}, or @code{foreach} form,
- or their names already contain a @samp{-} character. Thus a reference to
- @samp{foo} is the same as a reference to @samp{var-foo}.@refill
- X
- A few other Lisp extensions are available in @code{defmath} definitions:
- X
- @itemize @bullet
- @item
- The @code{elt} function accepts any number of index variables.
- Note that Calc vectors are stored as Lisp lists whose first
- element is the symbol @code{vec}; thus, @samp{(elt v 2)} yields
- the second element of vector @code{v}, and @samp{(elt m i j)}
- yields one element of a Calc matrix.
- X
- @item
- The @code{setq} function has been extended to act like the Common
- Lisp @code{setf} function. (The name @code{setf} is recognized as
- a synonym of @code{setq}.) Specifically, the first argument of
- @code{setq} can be an @code{nth}, @code{elt}, @code{car}, or @code{cdr} form,
- in which case the effect is to store into the specified
- element of a list. Thus, @samp{(setq (elt m i j) x)} stores @cite{x}
- into one element of a matrix.
- X
- @item
- A @code{for} looping construct is available. For example,
- @samp{(for ((i 0 10)) body)} executes @code{body} once for each
- binding of @cite{i} from zero to 10. This is like a @code{let}
- form in that @cite{i} is temporarily bound to the loop count
- without disturbing its value outside the @code{for} construct.
- Nested loops, as in @samp{(for ((i 0 10) (j 0 (1- i) 2)) body)},
- are also available. For each value of @cite{i} from zero to 10,
- @cite{j} counts from 0 to @cite{i-1} in steps of two. Note that
- @code{for} has the same general outline as @code{let}, except
- that each element of the header is a list of three or four
- things, not just two.
- X
- @item
- The @code{foreach} construct loops over elements of a list.
- For example, @samp{(foreach ((x (cdr v))) body)} executes
- @code{body} with @cite{x} bound to each element of Calc vector
- @cite{v} in turn. The purpose of @code{cdr} here is to skip over
- the initial @code{vec} symbol in the vector.
- X
- @item
- The @code{break} function breaks out of the innermost enclosing
- @code{while}, @code{for}, or @code{foreach} loop. If given a
- value, as in @samp{(break x)}, this value is returned by the
- loop. (Lisp loops otherwise always return @code{nil}.)
- X
- @item
- The @code{return} function prematurely returns from the enclosing
- function. For example, @samp{(return (+ x y))} returns @samp{x+y}
- as the value of a function. You can use @code{return} anywhere
- inside the body of the function.
- @end itemize
- X
- Non-integer numbers (and extremely large integers) cannot be included
- directly into a @code{defmath} definition. This is because the Lisp
- reader will fail to parse them long before @code{defmath} ever gets control.
- Instead, use the notation, @samp{:"3.1415"}. In fact, any algebraic
- formula can go between the quotes. For example,
- X
- @smallexample
- (defmath sqexp (x) ; sqexp(x) == sqrt(exp(x)) == exp(x*0.5)
- X (and (numberp x)
- X (exp :"x * 0.5")))
- @end smallexample
- X
- expands to
- X
- @smallexample
- (defun calcFunc-sqexp (x)
- X (and (math-numberp x)
- X (calcFunc-exp (math-mul x '(float 5 -1)))))
- @end smallexample
- X
- Note the use of @code{numberp} as a guard to ensure that the argument is
- a number first, returning @code{nil} if not. The exponential function
- could itself have been included in the expression, if we had preferred:
- @samp{:"exp(x * 0.5)"}. As another example, the multiplication-and-recursion
- step of @code{myfact} could have been written
- X
- @example
- :"n * myfact(n-1)"
- @end example
- X
- If a file named @file{.emacs} exists in your home directory, Emacs reads
- and executes the Lisp forms in this file as it starts up. While it may
- seem like a good idea to put your favorite @code{defmath} commands here,
- this has the unfortunate side-effect that parts of the Calculator must be
- loaded in to process the @code{defmath} commands whether or not you will
- actually use the Calculator! A better effect can be had by writing
- X
- @example
- (put 'calc-define 'thing '(progn
- X (defmath ... )
- X (defmath ... )
- ))
- @end example
- X
- @noindent
- @vindex calc-define
- The @code{put} function adds a @dfn{property} to a symbol. Each Lisp
- symbol has a list of properties associated with it. Here we add a
- property with a name of @code{thing} and a @samp{(progn ...)} form as
- its value. When Calc starts up, and at the start of every Calc command,
- the property list for the symbol @code{calc-define} is checked and the
- values of any properties found are evaluated as Lisp forms. The
- properties are removed as they are evaluated. The property names
- (like @code{thing}) are not used; you should choose something like the
- name of your project so as not to conflict with other properties.
- X
- The net effect is that you can put the above code in your @file{.emacs}
- file and it will not be executed until Calc is loaded. Or, you can put
- that same code in another file which you load by hand either before or
- after Calc itself is loaded.
- X
- The properties of @code{calc-define} are evaluated in the same order
- that they were added. They can assume that the Calc modules @file{calc.el},
- @file{calc-ext.el}, and @file{calc-macs.el} have been fully loaded, and
- that the @samp{*Calculator*} buffer will be the current buffer.
- X
- If your @code{calc-define} property only defines algebraic functions,
- you can be sure that it will have been evaluated before Calc tries to
- call your function, even if the file defining the property is loaded
- after Calc is loaded. But if the property defines commands or key
- sequences, it may not be evaluated soon enough. (Suppose it defines the
- new command @code{tweak-calc}; the user can load your file, then type
- @kbd{M-x tweak-calc} before Calc has had chance to do anything.) To
- protect against this situation, you can put
- X
- @example
- (run-hooks 'calc-check-defines)
- @end example
- X
- @findex calc-check-defines
- @noindent
- at the end of your file. The @code{calc-check-defines} function is what
- looks for and evaluates properties on @code{calc-define}; @code{run-hooks}
- has the advantage that it is quietly ignored if @code{calc-check-defines}
- is not yet defined because Calc has not yet been loaded.
- X
- Examples of things that ought to be enclosed in a @code{calc-define}
- property are @code{defmath} calls, @code{define-key} calls that modify
- the Calc key map, and any calls that redefine things defined inside Calc.
- Ordinary @code{defun}s need not be enclosed with @code{calc-define}.
- X
- @node Defining Simple Commands, Defining Stack Commands, Defining Functions, Lisp Definitions
- @subsection Defining New Simple Commands
- X
- @noindent
- @findex interactive
- If a @code{defmath} form contains an @code{interactive} clause, it defines
- a Calculator command. Actually such a @code{defmath} results in @emph{two}
- function definitions: One, a @samp{calcFunc-} function as was just described,
- with the @code{interactive} clause removed. Two, a @samp{calc-} function
- with a suitable @code{interactive} clause and some sort of wrapper to make
- the command work in the Calc environment.
- X
- In the simple case, the @code{interactive} clause has the same form as
- for normal Emacs Lisp commands:
- X
- @smallexample
- (defmath increase-precision (delta)
- X "Increase precision by DELTA." ; This is the "documentation string"
- X (interactive "p") ; Register this as a M-x-able command
- X (setq calc-internal-prec (+ calc-internal-prec delta)))
- @end smallexample
- X
- This expands to the pair of definitions,
- X
- @smallexample
- (defun calc-increase-precision (delta)
- X "Increase precision by DELTA."
- X (interactive "p")
- X (calc-wrapper
- X (setq calc-internal-prec (math-add calc-internal-prec delta))))
- X
- (defun calcFunc-increase-precision (delta)
- X "Increase precision by DELTA."
- X (setq calc-internal-prec (math-add calc-internal-prec delta)))
- @end smallexample
- X
- @noindent
- where in this case the latter function would never really be used! Note
- that since the Calculator stores small integers as plain Lisp integers,
- the @code{math-add} function will work just as well as the native
- @code{+} even when the intent is to operate on native Lisp integers.
- X
- @findex calc-wrapper
- The @samp{calc-wrapper} call invokes a macro which surrounds the body of
- the function with code that looks like this:
- X
- @smallexample
- X (let ((calc-command-flags nil))
- X (unwind-protect
- X (progn
- X (save-excursion
- X (calc-select-buffer)
- X @emph{body of function})
- X (calc-finish-command))
- X (calc-cleanup-command)))
- @end smallexample
- X
- @findex calc-select-buffer
- The @code{calc-select-buffer} function selects the @samp{*Calculator*}
- buffer if necessary, say, because the command was invoked from inside
- the @samp{*Calc Trail*} window.
- X
- @findex calc-finish-command
- The @code{calc-finish-command} function recomputes the line numbers
- for all stack entries if they have been changed.
- Also, if the @code{clear-message} flag is set
- it executes @samp{(message "")} to clear any lingering ``Working'' message
- out of the echo area.@refill
- X
- @findex calc-cleanup-command
- The @code{calc-cleanup-command} function normally aligns the stack window
- so that the top element of the stack is visible at the
- bottom of the window, and moves the cursor down to the bottom line.
- This can be suppressed by setting the @code{no-align}
- flag as described below. Also, it clears the Inverse and Hyperbolic
- flags (unless the @code{keep-flags} flag has been set), and updates the
- display of the mode line.@refill
- X
- @findex calc-set-command-flag
- You can call, for example, @code{(calc-set-command-flag 'no-align)} to set
- the above-mentioned command flags. The following command flags are
- recognized by Calc routines:
- X
- @table @code
- @item renum-stack
- Stack line numbers @samp{1:}, @samp{2:}, and so on must be renumbered
- after this command completes. This is set by routines like
- @code{calc-push}.
- X
- @item clear-message
- Calc should call @samp{(message "")} if this command completes normally.
- X
- @item no-align
- Do not move the cursor back to the @samp{.} top-of-stack marker.
- X
- @item position-point
- Use the variables @code{calc-position-point-line} and
- @code{calc-position-point-column} to position the cursor after
- this command finishes.
- X
- @item keep-flags
- Do not clear @code{calc-inverse-flag}, @code{calc-hyperbolic-flag},
- and @code{calc-keep-args-flag} at the end of this command.
- X
- @item do-edit
- Switch to buffer @samp{*Calc Edit*} after this command.
- @end table
- X
- @kindex Y
- @kindex Y ?
- @vindex calc-Y-help-msgs
- Calc reserves a special prefix key, shift-@kbd{Y}, for user-written
- extensions to Calc. There are no built-in commands that work with
- this prefix key; you must call @code{define-key} from Lisp (probably
- from inside a @code{calc-define} property) to add to it. Initially only
- @kbd{Y ?} is defined; it takes help messages from a list of strings
- (initially @code{nil}) in the variable @code{calc-Y-help-msgs}. All
- other undefined keys except for @kbd{Y} are reserved for use by
- future versions of Calc.
- X
- If you are writing a Calc enhancement which you expect to give to
- others, it is best to minimize the number of @kbd{Y}-key sequences
- you use. In fact, if you have more than one key sequence you should
- consider defining three-key sequences with @kbd{Y}, then a key that
- stands for your package, then a third key for the particular command
- within your package.
- X
- Users may wish to install several Calc enhancements, and it is possible
- that several enhancements will choose to use the same key. In the
- example below, a variable @code{inc-prec-base-key} has been defined
- to contain the key that identifies the @code{inc-prec} package. Its
- value is initially @code{"P"}, but a user can change this variable
- if necessary without having to modify the file.
- X
- Here is a complete file, @file{inc-prec.el}, which makes a @kbd{Y P I}
- command that increases the precision, and a @kbd{Y P D} command that
- decreases the precision.
- X
- @smallexample
- ;;; Increase and decrease Calc precision. Dave Gillespie, 5/31/91.
- ;;; (Include copyright or copyleft stuff here.)
- X
- (defvar inc-prec-base-key "P"
- X "Base key for inc-prec.el commands.")
- X
- (put 'calc-define 'inc-prec '(progn
- X
- (define-key calc-mode-map (format "Y%sI" inc-prec-base-key)
- X 'increase-precision)
- (define-key calc-mode-map (format "Y%sD" inc-prec-base-key)
- X 'decrease-precision)
- X
- (setq calc-Y-help-msgs
- X (cons (format "%s + Inc-prec, Dec-prec" inc-prec-base-key)
- X calc-Y-help-msgs))
- X
- (defmath increase-precision (delta)
- X "Increase precision by DELTA."
- X (interactive "p")
- X (setq calc-internal-prec (+ calc-internal-prec delta)))
- X
- (defmath decrease-precision (delta)
- X "Decrease precision by DELTA."
- X (interactive "p")
- X (setq calc-internal-prec (- calc-internal-prec delta)))
- X
- )) ; end of calc-define property
- X
- (run-hooks 'calc-check-defines)
- @end smallexample
- X
- @node Defining Stack Commands, Argument Qualifiers, Defining Simple Commands, Lisp Definitions
- @subsection Defining New Stack-Based Commands
- X
- @noindent
- To define a new computational command which takes and/or leaves arguments
- on the stack, a special form of @code{interactive} clause is used.
- X
- @example
- (interactive @var{num} @var{tag})
- @end example
- X
- @noindent
- where @var{num} is an integer, and @var{tag} is a string. The effect is
- to pop @var{num} values off the stack, resimplify them by calling
- @code{calc-normalize}, and hand them to your function according to the
- function's argument list. Your function may include @code{&optional} and
- @code{&rest} parameters, so long as calling the function with @var{num}
- parameters is legal.
- X
- Your function must return either a number or a formula in a form
- acceptable to Calc, or a list of such numbers or formulas. These value(s)
- are pushed onto the stack when the function completes. They are also
- recorded in the Calc Trail buffer on a line beginning with @var{tag},
- a string of (normally) four characters or less. If you omit @var{tag}
- or use @code{nil} as a tag, the result is not recorded in the trail.
- X
- As an example, the definition
- X
- @smallexample
- (defmath myfact (n)
- X "Compute the factorial of the integer at the top of the stack."
- X (interactive 1 "fact")
- X (if (> n 0)
- X (* n (myfact (1- n)))
- X (and (= n 0) 1)))
- @end smallexample
- X
- @noindent
- is a version of the factorial function shown previously which can be used
- as a command as well as an algebraic function. It expands to
- X
- @smallexample
- (defun calc-myfact ()
- X "Compute the factorial of the integer at the top of the stack."
- X (interactive)
- X (calc-slow-wrapper
- X (calc-enter-result 1 "fact"
- X (cons 'calcFunc-myfact (calc-top-list-n 1)))))
- X
- (defun calcFunc-myfact (n)
- X "Compute the factorial of the integer at the top of the stack."
- X (if (math-posp n)
- X (math-mul n (calcFunc-myfact (math-add n -1)))
- X (and (math-zerop n) 1)))
- @end smallexample
- X
- @findex calc-slow-wrapper
- The @code{calc-slow-wrapper} function is a version of @code{calc-wrapper}
- that automatically puts up a @samp{Working...} message before the
- computation begins. (This message can be turned off by the user
- with an @kbd{m w} (@code{calc-working}) command.)
- X
- @findex calc-top-list-n
- The @code{calc-top-list-n} function returns a list of the specified number
- of values from the top of the stack. It resimplifies each value by
- calling @code{calc-normalize}. If its argument is zero it returns an
- empty list. It does not actually remove these values from the stack.
- X
- @findex calc-enter-result
- The @code{calc-enter-result} function takes an integer @var{num} and string
- @var{tag} as described above, plus a third argument which is either a
- Calculator data object or a list of such objects. These objects are
- resimplified and pushed onto the stack after popping the specified number
- of values from the stack. If @var{tag} is non-@code{nil}, the values
- being pushed are also recorded in the trail.
- X
- Note that if @code{calcFunc-myfact} returns @code{nil} this represents
- ``leave the function in symbolic form.'' To return an actual empty list,
- in the sense that @code{calc-enter-result} will push zero elements back
- onto the stack, you should return the special value @samp{'(nil)}, a list
- containing the single symbol @code{nil}.
- X
- The @code{interactive} declaration can actually contain a limited
- Emacs-style code string as well which comes just before @var{num} and
- @var{tag}. Currently the only Emacs code supported is @samp{"p"}, as in
- X
- @example
- (defmath foo (a b &optional c)
- X (interactive "p" 2 "foo")
- X @var{body})
- @end example
- X
- In this example, the command @code{calc-foo} will evaluate the expression
- @samp{foo(a,b)} if executed with no argument, or @samp{foo(a,b,n)} if
- executed with a numeric prefix argument of @cite{n}.
- X
- The other code string allowed is @samp{"m"} (unrelated to the usual @samp{"m"}
- code as used with @code{defun}). It uses the numeric prefix argument as the
- number of objects to remove from the stack and pass to the function.
- In this case, the integer @var{num} serves as a default number of
- arguments to be used when no prefix is supplied.
- X
- @node Argument Qualifiers, Example Definitions, Defining Stack Commands, Lisp Definitions
- @subsection Argument Qualifiers
- X
- @noindent
- Anywhere a parameter name can appear in the parameter list you can also use
- an @dfn{argument qualifier}. Thus the general form of a definition is:
- X
- @example
- (defmath @var{name} (@var{param} @var{param...}
- X &optional @var{param} @var{param...}
- X &rest @var{param})
- X @var{body})
- @end example
- X
- @noindent
- where each @var{param} is either a symbol or a list of the form
- X
- @example
- (@var{qual} @var{param})
- @end example
- X
- The following qualifiers are recognized:
- X
- @table @samp
- @item complete
- @findex complete
- The argument must not be an incomplete vector, interval, or complex number.
- (This is rarely needed since the Calculator itself will never call your
- function with an incomplete argument. But there is nothing stopping your
- own Lisp code from calling your function with an incomplete argument.)@refill
- X
- @item integer
- @findex integer
- The argument must be an integer. If it is an integer-valued float
- it will be accepted but converted to integer form. Non-integers and
- formulas are rejected.
- X
- @item natnum
- @findex natnum
- Like @samp{integer}, but the argument must be non-negative.
- X
- @item fixnum
- @findex fixnum
- Like @samp{integer}, but the argument must fit into a native Lisp integer,
- which on most systems means less than 2^23 in absolute value. The
- argument is converted into Lisp-integer form if necessary.
- X
- @item float
- @findex float
- The argument is converted to floating-point format if it is a number or
- vector. If it is a formula it is left alone. (The argument is never
- actually rejected by this qualifier.)
- X
- @item @var{pred}
- The argument must satisfy predicate @var{pred}, which is one of the
- standard Calculator predicates. @xref{Predicates}.
- X
- @item not-@var{pred}
- The argument must @emph{not} satisfy predicate @var{pred}.
- @end table
- X
- For example,
- X
- @example
- (defmath foo (a (constp (not-matrixp b)) &optional (float c)
- X &rest (integer d))
- X @var{body})
- @end example
- X
- @noindent
- expands to
- X
- @example
- (defun calcFunc-foo (a b &optional c &rest d)
- X (and (math-matrixp b)
- X (math-reject-arg b 'not-matrixp))
- X (or (math-constp b)
- X (math-reject-arg b 'constp))
- X (and c (setq c (math-check-float c)))
- X (setq d (mapcar 'math-check-integer d))
- X @var{body})
- @end example
- X
- @noindent
- which performs the necessary checks and conversions before executing the
- body of the function.
- X
- @node Example Definitions, Calling Calc from Your Programs, Argument Qualifiers, Lisp Definitions
- @subsection Example Definitions
- X
- @noindent
- This section includes some Lisp programming examples on a larger scale.
- These programs make use of many of the Calculator's internal functions
- (@pxref{Internals}).
- X
- @menu
- * Sine Example::
- @end menu
- X
- @node Sine Example, , Example Definitions, Example Definitions
- @subsubsection The Sine Function
- X
- @noindent
- A somewhat limited sine function could be defined as follows, using the
- well-known Taylor series expansion for @samp{sin(x)}:
- X
- @smallexample
- (defmath mysin ((float (anglep x)))
- X (interactive 1 "mysn")
- X (setq x (to-radians x)) ; Convert from current angular mode.
- X (let ((sum x) ; Initial term of Taylor expansion of sin.
- X newsum
- X (nfact 1) ; "nfact" equals "n" factorial at all times.
- X (xnegsqr :"-(x^2)")) ; "xnegsqr" equals -x^2.
- X (for ((n 3 100 2)) ; Upper limit of 100 is a good precaution.
- X (working "mysin" sum) ; Display "Working" message, if enabled.
- X (setq nfact (* nfact (1- n) n)
- X x (* x xnegsqr)
- X newsum (+ sum (/ x nfact)))
- X (if (~= newsum sum) ; If newsum is "nearly equal to" sum,
- X (break)) ; then we are done.
- X (setq sum newsum))
- X sum))
- @end smallexample
- X
- The actual @code{sin} function in Calc works by first reducing the problem
- to a sine or cosine of a nonnegative number less than @c{$\pi \over 4$}
- @cite{pi/4}. This
- ensures that the Taylor series will converge quickly. Also, the calculation
- is carried out with two extra digits of precision to guard against cumulative
- round-off in @samp{sum}. Finally, complex arguments are allowed and handled
- by a separate algorithm.
- X
- @smallexample
- (defmath mysin ((float (scalarp x)))
- X (interactive 1 "mysn")
- X (setq x (to-radians x)) ; Convert from current angular mode.
- X (with-extra-prec 2 ; Evaluate with extra precision.
- X (cond ((complexp x)
- X (mysin-complex x))
- X ((< x 0)
- X (- (mysin-raw (- x))) ; Always call mysin-raw with x >= 0.
- X (t (mysin-raw x))))))
- X
- (defmath mysin-raw (x)
- X (cond ((>= x 7)
- X (mysin-raw (% x (two-pi)))) ; Now x < 7.
- X ((> x (pi-over-2))
- X (- (mysin-raw (- x (pi))))) ; Now -pi/2 <= x <= pi/2.
- X ((> x (pi-over-4))
- X (mycos-raw (- x (pi-over-2)))) ; Now -pi/2 <= x <= pi/4.
- X ((< x (- (pi-over-4)))
- X (- (mycos-raw (+ x (pi-over-2))))) ; Now -pi/4 <= x <= pi/4,
- X (t (mysin-series x)))) ; so the series will be efficient.
- @end smallexample
- X
- @noindent
- where @code{mysin-complex} is an appropriate function to handle complex
- numbers, @code{mysin-series} is the routine to compute the sine Taylor
- series as before, and @code{mycos-raw} is a function analogous to
- @code{mysin-raw} for cosines.
- X
- The strategy is to ensure that @cite{x} is nonnegative before calling
- @code{mysin-raw}. This function then recursively reduces its argument
- to a suitable range, namely, plus-or-minus @c{$\pi \over 4$}
- @cite{pi/4}. Note that each
- test, and particularly the first comparison against 7, is designed so
- that small roundoff errors cannnot produce an infinite loop. (Suppose
- we compared with @samp{(two-pi)} instead; if due to roundoff problems
- the modulo operator ever returned @samp{(two-pi)} exactly, an infinite
- recursion could result!) We use modulo only for arguments that will
- clearly get reduced, knowing that the next rule will catch any reductions
- that this rule misses.
- X
- If a program is being written for general use, it is important to code
- it carefully as shown in this second example. For quick-and-dirty programs,
- when you know that your own use of the sine function will never encounter
- a large argument, a simpler program like the first one shown is fine.
- X
- @node Calling Calc from Your Programs, Internals, Example Definitions, Lisp Definitions
- @subsection Calling Calc from Your Lisp Programs
- X
- @noindent
- A later section (@pxref{Internals}) gives a full description of
- Calc's internal Lisp functions. It's not hard to call Calc from
- inside your programs, but the number of these functions can be daunting.
- So Calc provides one special ``programmer-friendly'' function called
- @code{calc-eval} that can be made to do just about everything you
- need. It's not as fast as the low-level Calc functions, but it's
- much simpler to use!
- X
- It may seem that @code{calc-eval} itself has a daunting number of
- options, but they all stem from one simple operation.
- X
- In its simplest manifestation, @samp{(calc-eval "1+2")} parses the
- string @samp{"1+2"} as if it were a Calc algebraic entry and returns
- the result formatted as a string: @samp{"3"}.
- X
- Since @code{calc-eval} is on the list of recommended @code{autoload}
- functions, you don't need to make any special preparations to load
- Calc before calling @code{calc-eval} the first time. Calc will be
- loaded and initialized for you.
- X
- All the Calc modes that are currently in effect will be used when
- evaluating the expression and formatting the result.
- X
- @ifinfo
- @example
- X
- @end example
- @end ifinfo
- @subsubsection Additional Arguments to @code{calc-eval}
- X
- @noindent
- If the input string parses to a list of expressions, Calc returns
- the results separated by @samp{", "}. You can specify a different
- separator by giving a second string argument to @code{calc-eval}:
- SHAR_EOF
- true || echo 'restore of calc.texinfo failed'
- fi
- echo 'End of part 52'
- echo 'File calc.texinfo is continued in part 53'
- echo 53 > _shar_seq_.tmp
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-